package cn.icanci.test.aspect;

import cn.icanci.test.introduction.LittleUniverse;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * @author icanci
 * @date Created in 2021/03/02 23:58
 * @version 1.0
 */
@Aspect
@Order(1)
@Component
public class ServiceAspect {
    @Pointcut("execution(* cn.icanci.test.service..*.*(..))")
    public void embed() {

    }

    @Before("embed()")
    public void before(JoinPoint joinPoint) {
        System.out.println("开始调用：" + joinPoint);
    }

    @After("embed()")
    public void after(JoinPoint joinPoint) {
        System.out.println("调用完成：" + joinPoint);
    }

    @Around("embed()")
    public Object aroundMe(JoinPoint joinPoint) {
        long start = System.currentTimeMillis();
        Object returnValue = null;
        System.out.println("开始计时：" + joinPoint);
        try {
            returnValue = ((ProceedingJoinPoint) joinPoint).proceed();
            System.out.println("执行成功，结束计时 " + joinPoint);

        } catch (Throwable throwable) {
            throwable.printStackTrace();
            System.out.println("执行失败，结束计时 " + joinPoint);
        } finally {
            long endTime = System.currentTimeMillis();
            System.out.println("总耗时：" + (endTime - start) + " ms");
        }
        return returnValue;
    }

    @AfterReturning(pointcut = "embed()", returning = "returnValue")
    public void afterReturning(JoinPoint joinPoint, Object returnValue) {
        System.out.println("无论是否是空还是有值都返回 " + joinPoint + "，返回值：" + returnValue);
    }

    @AfterThrowing(pointcut = "embed()", throwing = "exception")
    public void afterThrowing(JoinPoint joinPoint, Exception exception) {
        System.out.println("抛出异常 " + joinPoint + ", 异常：" + exception.getMessage());
    }

    @DeclareParents(value = "cn.icanci.test.controller..*", defaultImpl = cn.icanci.test.introduction.impl.LittleUniverseImpl.class)
    public LittleUniverse littleUniverse;

}
